//建造者模式：用于构建复杂的对象
//有一个builder虚类，将各种类似的方法抽象放在虚类当中
//虚类的实现类ConcreteBuilder 负责具体的实现
//有一个指挥类，内部包含一个builder的指针，并且调用builder的过程，以避免用户直接调用复杂的对象
#include <iostream>
#include <memory>
#include <string>
//抽象建造者
class AbstractBuilder
{
public:
    using ptr = std::shared_ptr<AbstractBuilder>;
    virtual ~AbstractBuilder() {}
    virtual void buildHead() = 0;
    virtual void buildBody() = 0;
    virtual void buildLeftArm() = 0;
    virtual void buildRightArm() = 0;
    virtual void buildLeftLeg() = 0;
    virtual void buildRightLeg() = 0;
};
//具体建造者   建造一个瘦子
class BuildThin : public AbstractBuilder
{
public:
    using ptr = std::shared_ptr<BuildThin>;
    virtual void buildHead() override
    {
        std::cout << "画一个小萝卜头" << std::endl;
    }
    virtual void buildBody() override
    {
        std::cout << "画一个瘦不拉几的躯干" << std::endl;
    }
    virtual void buildLeftArm() override
    {
        std::cout << "画一个干巴巴的左胳膊" << std::endl;
    }
    virtual void buildRightArm() override
    {
        std::cout << "画一个干巴巴的右胳膊" << std::endl;
    }
    virtual void buildLeftLeg() override
    {
        std::cout << "画一个瘦骨嶙峋的左腿" << std::endl;
    }
    virtual void buildRightLeg() override
    {
        std::cout << "画一个瘦骨嶙峋的you腿" << std::endl;
    }
    virtual ~BuildThin()
    {
        std::cout << "瘦子被析构了" << std::endl;
    }
};
//具体建造者  建造一个胖子
class BuildFat : public AbstractBuilder
{
public:
    using ptr = std::shared_ptr<BuildFat>;
    virtual void buildHead() override
    {
        std::cout << "画一个肥猪头" << std::endl;
    }
    virtual void buildBody() override
    {
        std::cout << "画一个大腹便便的肚子" << std::endl;
    }
    virtual void buildLeftArm() override
    {
        std::cout << "画一个健硕的左胳膊" << std::endl;
    }
    virtual void buildRightArm() override
    {
        std::cout << "画一个健硕的右胳膊" << std::endl;
    }
    virtual void buildLeftLeg() override
    {
        std::cout << "画一个粗壮的左腿" << std::endl;
    }
    virtual void buildRightLeg() override
    {
        std::cout << "画一个粗壮的you腿" << std::endl;
    }
    virtual ~BuildFat()
    {
        std::cout << "胖子被析构了" << std::endl;
    }
};
//指挥者   用于指挥建造过程
class Director
{
public:
    using ptr = std::shared_ptr<Director>;
    Director(AbstractBuilder::ptr builder) : m_builder(builder) {}
    void setBuilder(AbstractBuilder::ptr builder)
    {
        m_builder = builder;
    }
    AbstractBuilder::ptr getBuilder()
    {
        return m_builder;
    }
    //具体的建造过程
    void construct()
    {
        m_builder->buildHead();
        m_builder->buildBody();
        m_builder->buildLeftArm();
        m_builder->buildRightArm();
        m_builder->buildLeftLeg();
        m_builder->buildRightLeg();
    }

private:
    AbstractBuilder::ptr m_builder;
};

int main(int argc, char **argv)
{
    BuildThin::ptr thin(new BuildThin());
    BuildFat::ptr fat(new BuildFat());
    std::cout << "**********建造一个瘦子**********" << std::endl;
    Director::ptr director(new Director(thin));
    director->construct();
    std::cout << "**********建造一个胖子**********" << std::endl;
    director->setBuilder(fat);
    director->construct();
    return 0;
}